package common

import (
	"fmt"
	"strconv"
)

type ListNode struct {
	Val  int
	Next *ListNode
}

// 最大的灵性是加入了一个新的头结点
func (head *ListNode) SwapPairs() *ListNode {
	// 节点数小于2，直接返回
	if head == nil || head.Next == nil {
		return head
	}
	newHead := &ListNode{}
	newHead.Next = head
	pre := newHead
	// 但前节点
	curr := head
	for curr != nil && curr.Next != nil {
		// 当前节点的下一节点
		next := curr.Next
		// 下下一个节点
		nextNext := curr.Next.Next
		// 交换当前节点和当前节点的下一节点
		pre.Next = next
		pre.Next.Next = curr
		// 更新下次交换的当前节点的前置节点
		pre = pre.Next.Next
		// 更新当前节点下一节点
		curr.Next = nextNext
		// 更新当前节点
		curr = curr.Next
	}
	return newHead.Next
}

// 相互交换,这样处理其实很慢，很垃圾，应该只循环一次来实现
func SwapEach(l *ListNode) *ListNode {
	i, j, len := 0, 1, 0

	other := l
	for other != nil {
		len++
		other = other.Next
	}

	for i < j && j < len {
		l = l.Swap(i, j)
		i += 2
		j += 2
	}
	fmt.Println(l)
	return l
}

// 向指定的index追加node,index 不能超过最大的长度
func (l *ListNode) Add(value, index int) *ListNode {
	i := 0

	if index == 0 { //first node
		root := &ListNode{value, l}
		return root
	}
	other := l
	for other != nil {
		i++
		if i == index {
			node1 := other.Next
			newnode := &ListNode{value, nil}
			other.Next = newnode
			newnode.Next = node1
		}
		other = other.Next
	}
	return l
}

// 向Link的末尾追加
func (l *ListNode) Append(value int) *ListNode {
	if l == nil {
		return &ListNode{value, nil}
	}
	other := l

	lastNode := &ListNode{}
	for other != nil {
		lastNode = other
		other = other.Next
		if other == nil {
			break
		}
	}

	lastNode.Next = &ListNode{value, nil}
	return lastNode
}

//删除指定index的node
func (l *ListNode) Remove(index int) *ListNode {
	if l == nil {
		return nil
	}
	other := l
	i := 0

	if index == 0 { //first node
		return l.Next
	}
	for other != nil {
		i++

		if index == i {
			if other.Next != nil {
				other.Next = other.Next.Next
			} else { // last node
				other.Next = nil
			}
		}

		other = other.Next
	}
	return l
}

// 交换两个node，
// 边界，index1=0，只有两个元素时需要做判断
func (l *ListNode) Swap(index1, index2 int) *ListNode {
	if l == nil {
		return l
	}
	other := l
	i := 0
	var node1, node1prev, node2, node2prev *ListNode

	if index1 >= index2 {
		return l
	}

	if index1 == 0 {
		node1 = l
		node1prev = nil
	}

	for other != nil {
		if index1-1 == i {
			node1prev = other
			node1 = node1prev.Next
		}
		if index2-1 == i {
			node2prev = other
			node2 = node2prev.Next
		}

		if node1 != nil && node2 != nil {
			break
		}
		i++
		other = other.Next
	}

	if node1 != nil && node2 != nil {
		if node1prev != nil {
			node1prev.Next = node2
		} else {
			l = node2
		}
		node1next := node1.Next
		node2next := node2.Next

		if node1next != node2 {
			node2.Next = node1next
		}
		if node2prev != node1 {
			node2prev.Next = node1
		} else {
			node2.Next = node1
		}
		node1.Next = node2next
	}
	return l
}

// 格式化输出
func (l *ListNode) String() string {
	lnode := l
	str := ""
	for lnode != nil {
		str += strconv.Itoa(lnode.Val) + "->"
		lnode = lnode.Next
	}
	return str
}

// arr to link,空数组返回nil
func ArrayToLink(arr []rune) *ListNode {
	if arr == nil {
		return nil
	}
	root := ListNode{0, nil}
	other := &root // 定义一个指针，指向第一个节点

	for i := 0; i < len(arr); i++ {
		tmp := ListNode{int(arr[i]), nil} // 创建临时节点
		other.Next = &tmp                 // 首节点的next 指向临时节点
		other = &tmp                      // other 向后移动一格
	}
	return root.Next
}

// 修改指定索引处的值
func (l *ListNode) Modify(value, index int) *ListNode {
	other := l
	i := 0
	for other != nil {
		if index == i {
			other.Val = value
			break
		}

		i++
		other = other.Next
	}
	return l
}

func (l *ListNode) Empty() bool {
	return l != nil
}
